package com.wlw.admin.plugindemo;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;

public class ProxyActivity extends Activity {
    private static final String TAG = "ProxyActivity";
    public static final String FROM = "extra.from";
    public static final int FROM_EXTERNAL = 0;
    public static final int FROM_INTERNAL = 1;

    public static final String EXTRA_DEX_PATH = "extra.dex.path";
    public static final String EXTRA_CLASS = "extra.class";

    private String mClass;
    private String mDexPath;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDexPath = getIntent().getStringExtra(EXTRA_DEX_PATH);
        Log.e("dex path", mDexPath);
        mClass = getIntent().getStringExtra(EXTRA_CLASS);
        if (mClass == null) {
            launchTargetActivity();
        } else {
            launchTargetActivity(mClass);
        }
//       onProxy();
    }

    private void launchTargetActivity() {
        PackageInfo packageInfo = getPackageManager().getPackageArchiveInfo(mDexPath, PackageManager.GET_ACTIVITIES);
        if (packageInfo.activities != null) {

            mClass = packageInfo.activities[0].name;
            launchTargetActivity(mClass);
        }
    }

    private void launchTargetActivity(String mClass) {
        File dexOutPutDir = getDir("dex", Context.MODE_PRIVATE);
        DexClassLoader dexClassLoader = new DexClassLoader(mDexPath, dexOutPutDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
        Log.e(TAG, "mClass = " + mClass);
        try {
            Class<?> localClass = dexClassLoader.loadClass(mClass);
            Constructor<?> localConstructor = localClass.getConstructor();
            Object instance = localConstructor.newInstance();

            Method setProxy = localClass.getMethod("setProxy", Activity.class);
            setProxy.setAccessible(true);
            setProxy.invoke(instance, this);

            Method onCreate = localClass.getDeclaredMethod("onCreate", Bundle.class);
            onCreate.setAccessible(true);
            Bundle bundle = new Bundle();
            bundle.putInt(FROM, FROM_EXTERNAL);
            onCreate.invoke(instance, bundle);
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private void onProxy() {
        List<PluginBean> plugins = findAllPlugin();
        for (PluginBean plugin : plugins) {
            Context pluginContext = null;
            try {
                pluginContext = this.createPackageContext(plugin.pkgName, CONTEXT_IGNORE_SECURITY | CONTEXT_INCLUDE_CODE);
                PathClassLoader pathClassLoader = new PathClassLoader(pluginContext.getPackageResourcePath(), ClassLoader.getSystemClassLoader());
                Class<?> localClass = Class.forName(plugin.pkgName + ".MainActivity", true, pathClassLoader);

                Constructor<?> localConstructor = localClass.getConstructor();
                Object instance = localConstructor.newInstance();
                Method setProxy = localClass.getMethod("setProxy", Activity.class);
                setProxy.setAccessible(true);
                setProxy.invoke(instance, this);

                Method onCreate = localClass.getDeclaredMethod("onCreate", Bundle.class);
                onCreate.setAccessible(true);
                Bundle bundle = new Bundle();
                bundle.putInt(FROM, FROM_EXTERNAL);

                onCreate.invoke(instance, bundle);
            } catch (PackageManager.NameNotFoundException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    private List<PluginBean> findAllPlugin() {
        List<PluginBean> pluginBeans = new ArrayList<>();
        PackageManager pm = getPackageManager();
        List<PackageInfo> packageInfo = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
        for (PackageInfo info : packageInfo) {
            String pkgName = info.packageName;
            String sharedUserId = info.sharedUserId;
            if (sharedUserId != null && sharedUserId.equals("com.wlw.admin.plugin")
                    && !pkgName.equals(getPackageName())) {
                String label = pm.getApplicationLabel(info.applicationInfo).toString();
                PluginBean bean = new PluginBean(label, pkgName);
                pluginBeans.add(bean);
            }
        }
        return pluginBeans;
    }
}
